<template>
  <div class="upload-wrapper">
    <div class="list">
      <div class="list-item" v-for="(item, index) in fileList" :key="index">
        <img :src="item" object-fit="contain" @click="showImage(index)" />
        <x-icon
          class="del-icon"
          type="ios-close"
          size="20"
          fill="#fff"
          @click="deleteFile(index)"
        ></x-icon>
      </div>
      <div class="upload-icon">
        <img class="needsclick" src="../../../assets/icon/upLoad.png" @click="chooseFile" />
        <label for="input" ref="input">
          <input class="needsclick" id="input" type="file" @change="onChange" :accept="accept" />
        </label>
      </div>
    </div>
    <div v-transfer-dom>
      <loading :show="loading" text="正在上传"></loading>
    </div>
    <showImg
      :list="fileList"
      :show.sync="showImg"
      :index="showImgIndex"
    ></showImg>
  </div>
</template>
<script>
import Exif from "exif-js";
import showImg from "@/components/common/showImg/showImg";
import { Loading, TransferDom } from "vux";

export default {
  name: "upload",
  directives: {
    TransferDom
  },
  components: {
    Loading,
    showImg
  },
  data() {
    return {
      imgUrl: "",
      showImgIndex: 0,
      showImg: false
    };
  },
  props: {
    disabled: Boolean,
    accept: {
      type: String,
      default: "image/*"
    },
    fileList: {
      type: Array,
      default: () => []
    },
    maxSize: {
      type: [Number, String],
      default: Number.MAX_VALUE
    },
    maxCount: {
      type: [Number, String],
      default: Number.MAX_VALUE
    },
    loading: {
      type: Boolean,
      default: false
    },
    deletable: {
      type: Boolean,
      default: true
    },
    showUpload: {
      type: Boolean,
      default: true
    },
    previewImage: {
      type: Boolean,
      default: true
    },
    previewFullImage: {
      type: Boolean,
      default: true
    },
    imageFit: {
      type: String,
      default: "cover"
    },
    resultType: {
      type: String,
      default: "dataUrl"
    },
    uploadIcon: {
      type: String,
      default: "photograph"
    },
    fileStream: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    getDetail(index = this.fileList.length) {
      return {
        name: this.name,
        index
      };
    },
    onChange(event) {
      let { files } = event.target;
      if (this.disabled || !files.length) {
        return;
      }
      files = files.length === 1 ? files[0] : [].slice.call(files);
      this.readFile(files);
    },

    readFile(files) {
      const oversize = this.isOversize(files, this.maxSize);
      if (this.fileList.length >= this.maxCount) {
        this.resetInput();
        this.$emit("overcount");
        return;
      }

      this.onAfterRead(files, oversize);
    },
    onAfterRead(files, oversize) {
      this.resetInput();

      let validFiles = files;
      if (oversize) {
        let oversizeFiles = files;
        if (Array.isArray(files)) {
          oversizeFiles = [];
          validFiles = [];
          files.forEach(item => {
            if (item.file) {
              if (item.file.size > this.maxSize) {
                oversizeFiles.push(item);
              } else {
                validFiles.push(item);
              }
            }
          });
        } else {
          validFiles = null;
        }
        this.$emit("oversize", oversizeFiles, this.getDetail());
      }
      const isValidFiles = Array.isArray(validFiles)
        ? Boolean(validFiles.length)
        : Boolean(validFiles);
      if (isValidFiles) {
        this.$emit("input", [...this.fileList, ...this.toArray(validFiles)]);
        if (this.fileStream) {
          this.changeBase64(validFiles);
        } else {
          this.$emit("afterRead", validFiles, this.getDetail());
        }
      }
    },

    changeBase64(file) {
      let self = this;
      let Orientation;
      //去获取拍照时的信息，解决拍出来的照片旋转问题
      Exif.getData(file, function() {
        Orientation = Exif.getTag(this, "Orientation");
      });
      console.log(Orientation);
      //判断支不支持FileReader
      if (!file || !window.FileReader) return;
      if (/^image/.test(file.type)) {
        //创建一个reader
        let reader = new FileReader();
        //将图片转成base64格式
        reader.readAsDataURL(file);
        //读取成功后的回调
        reader.onloadend = function() {
          let result = this.result;
          let img = new Image();
          img.src = result;
          // console.log("********未压缩前的图片大小********");
          // console.log(result.length);
          img.onload = function() {
            let data = self.compress(img, "");
            self.$emit("afterRead", data, self.getDetail());
          };
        };
      }
    },
    // 压缩图片
    compress(img, Orientation) {
      let canvas = document.createElement("canvas");
      let ctx = canvas.getContext("2d");
      let initSize = img.src.length;
      let width = img.width;
      let height = img.height;
      canvas.width = width;
      canvas.height = height;
      // 铺底色
      ctx.fillStyle = "#fff";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(img, 0, 0, width, height);
      //修复ios上传图片的时候 被旋转的问题
      if (Orientation != "" && Orientation != 1) {
        switch (Orientation) {
          case 6: //需要顺时针（向左）90度旋转
            this.rotateImg(img, "left", canvas);
            break;
          case 8: //需要逆时针（向右）90度旋转
            this.rotateImg(img, "right", canvas);
            break;
          case 3: //需要180度旋转
            this.rotateImg(img, "right", canvas); //转两次
            this.rotateImg(img, "right", canvas);
            break;
        }
      }
      //进行最小压缩
      let ndata = canvas.toDataURL("image/jpeg", 0.3);
      // console.log("*******压缩后的图片大小*******");
      // console.log(ndata)
      // console.log(ndata.length);
      return ndata;
    },
    rotateImg(img, direction, canvas) {
      //最小与最大旋转方向，图片旋转4次后回到原方向
      const min_step = 0;
      const max_step = 3;
      if (img == null) return;
      //img的高度和宽度不能在img元素隐藏后获取，否则会出错
      let height = img.height;
      let width = img.width;
      let step = 2;
      if (step == null) {
        step = min_step;
      }
      if (direction == "right") {
        step++;
        //旋转到原位置，即超过最大值
        step > max_step && (step = min_step);
      } else {
        step--;
        step < min_step && (step = max_step);
      }
      //旋转角度以弧度值为参数
      let degree = (step * 90 * Math.PI) / 180;
      let ctx = canvas.getContext("2d");
      switch (step) {
        case 0:
          canvas.width = width;
          canvas.height = height;
          ctx.drawImage(img, 0, 0);
          break;
        case 1:
          canvas.width = height;
          canvas.height = width;
          ctx.rotate(degree);
          ctx.drawImage(img, 0, -height);
          break;
        case 2:
          canvas.width = width;
          canvas.height = height;
          ctx.rotate(degree);
          ctx.drawImage(img, -width, -height);
          break;
        case 3:
          canvas.width = height;
          canvas.height = width;
          ctx.rotate(degree);
          ctx.drawImage(img, -width, 0);
          break;
      }
    },
    deleteFile(index) {
      this.$emit("delete", index);
    },

    resetInput() {
      /* istanbul ignore else */
      if (this.$refs.input) {
        this.$refs.input.value = "";
      }
    },

    showImage(index) {
      this.showImgIndex = index;
      this.showImg = true;
    },
    chooseFile() {
      if (this.disabled) {
        return;
      }
      /* istanbul ignore else */
      if (this.$refs.input) {
        this.$refs.input.click();
      }
    },

    isOversize(files, maxSize) {
      return this.toArray(files).some(file => file.size > maxSize);
    },
    toArray(item) {
      if (Array.isArray(item)) {
        return item;
      }
      return [item];
    }
  }
};
</script>
<style lang="less">
.upload-dialog {
  .img-close {
    text-align: right;
    margin-right: 24px;
    margin-top: 30px;
  }
  .show-img {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 80vh;
    img {
      max-width: 100%;
      height: auto;
    }
  }
}
</style>
<style lang="less" scoped>
.upload-wrapper {
  .list {
    display: flex;
    flex-wrap: wrap;
    margin-top: 8px;
    .list-item {
      height: 48px;
      display: flex;
      align-items: center;
      margin-right: 12px;
      margin-bottom: 6px;
      position: relative;
      img {
        width: 48px;
        height: auto;
        max-height: 100%;
      }
      .del-icon {
        position: absolute;
        top: -10px;
        right: -10px;
      }
    }
    .upload-icon {
      img {
        width: 48px;
        height: 48px;
      }
      input {
        width: 0;
        height: 0;
        opacity: 0;
      }
    }
  }
}
</style>
